﻿using CleanArchitecture.Core.Interfaces;
using CleanArchitecture.Core.SharedKernel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace CleanArchitecture.Core.Handlers
{
    // https://gist.github.com/jbogard/54d6569e883f63afebc7
    // http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
    public class DomainEventDispatcher : IDomainEventDispatcher
    {
        public DomainEventDispatcher()
        {
        }

        /// <summary>
        /// 要使用本方法，必须赋值完整的消息对象，例：
        /// _dispatcher.Dispatch(new EntityInsertedEvent<ToDoItem>(new ToDoItem()));
        /// 否则无法通过通过Ioc方式(DependencyRegistrar)反射加载对应的处理消息对象并调用消息响应处理方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="domainEvent"></param>
        public void Dispatch<T>(T domainEvent) where T : BaseDomainEvent
        {
            //DavidLee 2019/11/12 更改消息派发机制在接口容器注册时 see DependenceyRegistrar.cs
            //进行所有派发消息处理类的 接口-实现类注册绑定。通过容器获取
            //Type handlerType = typeof(IHandle<>).MakeGenericType(domainEvent.GetType());
            //Type wrapperType = typeof(DomainEventHandler<>).MakeGenericType(domainEvent.GetType());
            //IEnumerable handlers = (IEnumerable)EngineContext.Current.Resolve(typeof(IEnumerable<>).MakeGenericType(handlerType));
            //IEnumerable<DomainEventHandler<T>> wrappedHandlers = handlers.Cast<object>()
            //    .Select(handler => (DomainEventHandler<T>)Activator.CreateInstance(wrapperType, handler));

            //foreach (DomainEventHandler handler in wrappedHandlers)
            //{
            //    handler.Handle(domainEvent);
            //}
            var wrappedHandlers = EngineContext.Current.ResolveAll<IHandle<T>>().ToList();
            foreach(IHandle<T> handle in wrappedHandlers)
            {
                handle.Handle(domainEvent);
            }
        }
    }
}
